<?php
/**
 * ltpatoken生成与解析类
 * @author nishuihanlong <crastalsxq@qq.com>
 */
namespace Nishuihanlong;


/**
 * $ltpatoken = new Ltpatoken();
 * $token=$ltpatoken->genToken($secretKey);
 * $loginName=$ltpatoken->getToken($cookie);
 */
class Ltpatoken
{
    /**
     * @param string $key
     * @param string $loginName
     * @param int $expirationHours
     * @return string 返回token值
     */
    public function genToken(string $key,string $loginName="nishuihanlong",int $expirationHours=2): string
    {
        //$str="2010-03-12 00:21:49";
        //$timeStr=strtotime($str);
        //$octStr=strtoupper(dechex($timeStr));
        //echo $octStr;

        $nHeader = $this->getBytes('0123');
        $time=time();
        $createTime = strtoupper(dechex($time));
        $nCreateTime=$this->getBytes($createTime);
        $expirationTime = strtoupper(dechex($time + $expirationHours * 60 * 60));
        $nExpirationTime=$this->getBytes($expirationTime);
        $username = $loginName;
        $nUsername=$this->getBytes($username);
        $nkey=$this->getBytes(base64_decode($key));

        $sha1Orign=array();
        list($item, $sha1Orign) = $this->mergeArray($nHeader, $sha1Orign);
        list($item, $sha1Orign) = $this->mergeArray($nCreateTime, $sha1Orign);
        list($item, $sha1Orign) = $this->mergeArray($nExpirationTime, $sha1Orign);
        list($item, $sha1Orign) = $this->mergeArray($nUsername, $sha1Orign);
        list($item, $sha1Orign) = $this->mergeArray($nkey, $sha1Orign);

        $sha1=sha1($this->toStr($sha1Orign),true);
        $nSha1=$this->getBytes($sha1);

        $token=array();
        list($item, $token) = $this->mergeArray($nHeader, $token);
        list($item, $token) = $this->mergeArray($nCreateTime, $token);
        list($item, $token) = $this->mergeArray($nExpirationTime, $token);
        list($item, $token) = $this->mergeArray($nUsername, $token);
        list($item, $token) = $this->mergeArray($nSha1, $token);

        $tokenStr=base64_encode($this->toStr($token));
        return $tokenStr;
    }


    /**
     * @param string $key 共享密钥
     * @param string $token 获取的token值
     * @return string 返回登陆用户名
     */
    public function parseToken(string $key,string $token): string
    {
        $result=["code"=>0,"result"=>""];
        $tokenBytes=$this->getBytes(base64_decode($token));

        $nKey=$this->getBytes(base64_decode($key));

        $nOldSha1=array_slice($tokenBytes,count($tokenBytes)-20,20);
        $nArray=array_slice($tokenBytes,0,count($tokenBytes)-20);

        $nExpirationTime=array_slice($tokenBytes,12,8);
        $expirationTime=$this->toStr($nExpirationTime);
        $iExpirationTime=hexdec(strtolower($expirationTime));

        $nUsername=array_slice($tokenBytes,20,count($tokenBytes)-40);
        $loginName=$this->toStr($nUsername);

        $nNewArr=array();
        list($item, $nNewArr) = $this->mergeArray($nArray, $nNewArr);
        list($item, $nNewArr) = $this->mergeArray($nKey, $nNewArr);

        $sha1=sha1($this->toStr($nNewArr),true);
        $nNewSha1=$this->getBytes($sha1);

        //校验是否篡改
        if ($nOldSha1==$nNewSha1)
        {
            $result['code']=1;
            $result['result']=$loginName;
        }else{
            $result['code']=0;
            $result['result']='解析失败，token被篡改';
            return json_encode($result);
        }
        //校验是否过期
        $time=time();
        if ($iExpirationTime>=$time){
            $result['code']=1;
            $result['result']=$loginName;
        }else{
            $result['code']=0;
            $result['result']='token无效，已过期';
            return json_encode($result);
        }
        return json_encode($result);
    }

    /**
     * @param $string string 字符串转字节数组
     * @return array 返回字节数组
     */
    private function getBytes($string):array
    {
        $bytes = array();
        for($i = 0; $i < strlen($string); $i++){    //遍历每一个字符 用ord函数把它们拼接成一个php数组
            $bytes[] = ord($string[$i]);
        }
        return $bytes;
    }

    /**
     * @param $bytes array 字节数组
     * @return string 返回字符串
     */
    private function toStr($bytes):string
    {
        $str = '';
        foreach($bytes as $ch) {
            $str .= chr($ch);    //这里用chr函数
        }
        return $str;
    }

    /**
     * @param array $arr 数组字符合并
     * @param array $result
     * @return array
     */
    private function mergeArray(array $arr, array $result): array
    {
        $item='';
        foreach ($arr as $item) {
            array_push($result, $item);
        }
        return array($item, $result);
    }
}